package dk.aiszone.lang.messer.autosource;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import dk.aiszone.lang.autosource.generatorobjects.interfaces.GeneratorObject;
import dk.aiszone.lang.autosource.generatorobjects.interfaces.SimpleBlockObject;
import dk.aiszone.lang.messer.autosource.interfaces.ComplexStatement;

/**
 * <code>BlockObject</code> representing a for-statement.
 * 
 * @author Ais
 */
public class ForStatement extends GeneratorObject implements ComplexStatement, SimpleBlockObject {

    private final List<SimpleBlockObject> arg0;
    private final SimpleBlockObject arg1;
    private final List<SimpleBlockObject> arg2;
    private final SimpleBlockObject body;

    /**
     * Constructor for the for-statement.
     * 
     * @param arg0
     *            The first argument in the for-statement <code>for(<b>arg0</b>; arg1; arg2) {</code><br>
     *            <code>List</code> of initializations.
     * @param arg1
     *            The second argument in the for-statement <code>for(arg0; <b>arg1</b>; arg2) {</code>
     * @param arg2
     *            The third argument in the for-statement <code>for(arg0; arg1; <b>arg2</b>) {</code><br>
     *            <code>List</code> of updates.
     * @param body
     *            The body of the for-statement.
     */
    public ForStatement(List<SimpleBlockObject> arg0, SimpleBlockObject arg1, List<SimpleBlockObject> arg2, BlockStatement body) {
        this.arg0 = arg0;
        this.arg1 = arg1;
        this.arg2 = arg2;

        this.body = body;
    }

    @Override
    public Object clone() {
        List<SimpleBlockObject> arg0clone = new ArrayList<SimpleBlockObject>();
        for (SimpleBlockObject simpleBlockObject : arg0) {
            arg0clone.add((SimpleBlockObject)simpleBlockObject.clone());
        }

        List<SimpleBlockObject> arg2clone = new ArrayList<SimpleBlockObject>();
        for (SimpleBlockObject simpleBlockObject : arg2clone) {
            arg2clone.add((SimpleBlockObject)simpleBlockObject.clone());
        }

        return new ForStatement(arg0clone, (SimpleBlockObject)arg1.clone(), arg2clone, (BlockStatement)body.clone());
    }

    @Override
    public String toJava() {
        StringBuilder sb = new StringBuilder();
        sb.append("for(");
        for (Iterator<SimpleBlockObject> iterator = arg0.iterator(); iterator.hasNext();) {
            sb.append(iterator.next().toJava());
            if (iterator.hasNext()) {
                sb.append(", ");
            }
        }
        sb.append("; ").append(arg1.toJava()).append("; ");
        for (Iterator<SimpleBlockObject> iterator = arg2.iterator(); iterator.hasNext();) {
            sb.append(iterator.next().toJava());
            if (iterator.hasNext()) {
                sb.append(", ");
            }
        }

        sb.append(") {\n");
        if (body != null) {
            sb.append(body.toJava());
        }
        sb.append("\n}");
        return sb.toString();
    }

    @Override
    public SimpleBlockObject getChild(int index) {
        if (index < (arg0 != null ? arg0.size() : 0)) {
            return arg0.get(index);
        }

        index -= (arg0 != null ? arg0.size() : 0);
        if (index < (arg1 != null ? 1 : 0)) {
            return arg1;
        }

        index -= (arg1 != null ? 1 : 0);
        if (index < (arg2 != null ? arg2.size() : 0)) {
            return arg2.get(index);
        }

        index -= (arg2 != null ? arg2.size() : 0);
        return body.getChild(index);
    }

    @Override
    public int getChildCount() {
        int count = (arg0 != null ? arg0.size() : 0);
        count += (arg1 != null ? 1 : 0);
        count += (arg2 != null ? arg2.size() : 0);
        count += (body != null ? body.getChildCount() : 0);
        return count;
    }
}